﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using KalamburyCanvas;
//using KalamburyClient.Kalambury;
using AsynchRequest;
using KalamburyManager.Kalambury;
using KalamburyManager;


namespace KalamburyClient
{
    public partial class MainForm : Form
    {
        static string msg1 = "You are a painter. You can't communicate with other users";
        KalamburyGameClient client = null;
        
        User user = null;
        User CurPainter = null;
        
        string currentAnswer;
        bool IarePainter = false;
        bool Joined = false;
        bool createdCompleted = false;
        GameStatus currentStatus;
        Timer checkIsOk = new Timer() { Interval = 5000 };
        KalamburyManager.KalamburyGameManager manager;

        string roomName { get; set; }

        public MainForm()
        {
            
            InitializeComponent();
            this.roomName = String.Empty;
            this.client = new KalamburyGameClient();
            this.currentStatus = GameStatus.NoRoom;
            this.lblRoom.Text = "";
            this.listViewUsers.Items.Clear();
            this.checkIsOk.Enabled = true;
            this.checkIsOk.Tick +=new EventHandler((s, ea) => 
            {
                if (!createdCompleted)
                {
                    createdCompleted = true; //completed with error
                    MessageBox.Show("Bład połączenia. Możliwe przyczyny błędu:\n-Serwis jest nieczynny\n-Problem z internetem\n-Źle skonfigurowany firewall", "błąd", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    this.Close();

                }
            });
            
        }

        bool iAmPainter = false;
        void manager_StatusChanged(object sender, KalamburyManagerChangeGameStatus e)
        {
            InvokeOperation(() =>
            {
                switch (e.Status)
                {
                    case GameStatus.NoRoom:
                        //do nothing
                        this.lblRoomStatus.Text = "NoRoom";
                        this.currentStatus = GameStatus.NoRoom;
                        this.SetManager(false, true);
                        break;
                    case GameStatus.New:
                        if (currentStatus == GameStatus.During)
                        {
                            //User win = client.WhoWin(user);
                            //if (win != null)
                            //{
                                lblRoomStatus.Text = "New";
                                btnStartGame.Text = "Ready";
                                SetManager(false, true);
                            //}
                            break;
                        }
                        else
                        {
                            lblRoomStatus.Text = "New";
                        }

                        currentStatus = GameStatus.New;
                        break;
                    case GameStatus.Wait:
                        currentStatus = GameStatus.Wait;
                        lblRoomStatus.Text = "Wait..";
                        SetManager(false, true);
                        break;
                    case GameStatus.During:  //block buttons
                        lblRoomStatus.Text = "Playing";
                        btnStartGame.Text = "Ready";
                        if (currentStatus == GameStatus.Wait || currentStatus == GameStatus.New)
                        {
                            var painter = manager.GetPainter();
                            lblPainter.Text = painter.Name;
                            if (painter.Name == user.Name)
                            {
                                iAmPainter = true;
                                manager.CheckImage(false);
                                //current user in painter
                                txtChatMsg.Enabled = false;
                                txtChatMsg.Text = msg1;
                                kalamburyCanvasControl.OnlyView = false;
                                lblAnswer.Text = manager.GetAnswer();
                            }
                            else
                            {
                                //this user tries to guess
                                iAmPainter = false;
                                lblAnswer.Text = String.Empty;
                                kalamburyCanvasControl.OnlyView = true;
                                txtChatMsg.Enabled = true;
                                manager.CheckImage(true);
                            }
                            kalamburyCanvasControl.Clear();
                        }
                        currentStatus = GameStatus.During;
                        SetManager(true, true);
                        break;
                    case GameStatus.EndSmbKnown: //end game 
                        if (currentStatus != GameStatus.EndSmbKnown)
                        {
                            this.currentStatus = GameStatus.EndSmbKnown;
                            this.lblAnswer.Text = String.Empty;
                            this.kalamburyCanvasControl.Clear();
                            this.kalamburyCanvasControl.OnlyView = true;
                            this.txtChatMsg.Enabled = true;
                            if (txtChatMsg.Text == msg1)
                                txtChatMsg.Text = "";
                            //User winner = client.WhoWin(user);
                            //MessageBox.Show(winner.Name + " win!");
                            //this.lblRoomStatus.Text = winner.Name + " win";
                            this.btnStartGame.Text = "Ready";
                            this.SetManager(false, true);
                        }
                        break;
                    case GameStatus.Timeout: //end game
                        if (iAmPainter)
                            manager.ResetRoom();
                        iAmPainter = false;

                        this.currentStatus = GameStatus.Timeout;
                        this.lblRoomStatus.Text = "Timeout...";
                        this.lblAnswer.Text = String.Empty;
                        this.kalamburyCanvasControl.Clear();
                        this.kalamburyCanvasControl.OnlyView = true;
                        this.txtChatMsg.Enabled = true;
                        this.btnStartGame.Text = "Ready";
                        if (txtChatMsg.Text == msg1)
                            txtChatMsg.Text = "";
                        this.SetManager(false, true);
                        break;
                    default:
                        MessageBox.Show("error");
                        break;
                }
            });
        }

        void manager_UsersCallback(object sender, KalamburyManagerUsersEventsArgs e)
        {
            InvokeOperation(() =>
            {
            this.PopulateUserList(e.Users);
            });
        }

        void SetManager(bool image, bool status)
        {
            if (manager != null)
            {
                //manager.EnableGameStatusMonitor = status;
                manager.EnableImageStatusMonitor = image;
            }
        }

        void manager_NewImage(object sender, KalamburyManagerNewImageEventArgs e)
        {
            InvokeOperation(() =>
                {
                    kalamburyCanvasControl.PutImage(e.ImageInString);
                });
        }

        private bool CreateUser(string userName)
        {
            var result = client.NewUser(userName);
            this.createdCompleted = true;
            switch (result.Key)
            {
                case CreateUserStaus.UserExists:
                    MessageBox.Show("Podana nazwa jest używana", "Bład", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);
                    return false;
                case CreateUserStaus.OK:
                    user = result.Value;
                    manager = new KalamburyGameManager(client, user);
                    manager.NewImage += new KalamburyGameManager.KalamburyManagerNewImageEventHandler(manager_NewImage);
                    manager.StatusChanged += new KalamburyGameManager.KalamburyManagerChangeStatusEventHandler(manager_StatusChanged);
                    manager.UsersCallback += new KalamburyGameManager.KalamburyManagerCheckEventHandler(manager_UsersCallback);
                    manager.RoomsCallback += new KalamburyGameManager.KalamburyManagerCheckRoomsEventHandler(manager_RoomsCallback);
                    manager.MessagesCallback += new KalamburyGameManager.KalamburyManagerMessagesEventHandler(manager_MessagesCallback);
                    return true;
                case CreateUserStaus.Fail:
                    MessageBox.Show("Bład. Skontaktuj się z dostawcą oprogramowania", "Bład");
                    return false;
                default:
                    return false;
            }
        }

        void manager_MessagesCallback(object sender, KalamburyManagerMessageCallbackEventArgs e)
        {
            InvokeOperation(() =>
     {
         txtRichChat.Text = "";
         txtChatMsg.Focus();
         StringBuilder sb = new StringBuilder();
         string msg = e.Messages;
         var split = msg.Split
            (Environment.NewLine.ToCharArray()).Reverse();
        foreach (string s in split)
        {
            if (s.Trim() != "")
                sb.AppendLine(s);
        }

         txtRichChat.Text = sb.ToString();
         //txtChatMsg.SelectionStart = txtChatMsg.Text.Length - 1;
         txtChatMsg.ScrollToCaret();
     });
        }

        void manager_RoomsCallback(object sender, KalamburyManagerRoomCallbackEventArgs e)
        {
            InvokeOperation(() =>
            {
                string selected = null;
                if (listBoxRooms.SelectedItem != null)
                    selected = (string)listBoxRooms.SelectedItem;
                bool stillExists = false;
                listBoxRooms.Items.Clear();
                e.Rooms.ForEach(r =>
                {
                    if (r == selected)
                        stillExists = true;
                    listBoxRooms.Items.Add(r);
                });
                
                if (stillExists)
                    listBoxRooms.SelectedItem = selected;
            });
        }

        private void btnGetRooms_Click(object sender, EventArgs e)
        {
            listBoxRooms.Items.Clear();
            var list = manager.GetRoomsNames();
            list.ForEach((a) =>
            {
                listBoxRooms.Items.Add(a);
            });

        }

        void kalamburyCanvasControl_NewImage(object sender, KalamburyCanvas.KalamburyControlEventArg e)
        {
            manager.PutNewImage(e.ImageInString);
        }

        private void btnCreateRoom_Click(object sender, EventArgs e)
        {
            string roomName = txtCreateRoom.Text;
            if (txtCreateRoom.Text != "")
            {
                
                bool result = manager.CreateRoom(txtCreateRoom.Text);
                txtCreateRoom.Text = "";
                if (!result)
                {
                    MessageBox.Show("There is a room with the same name");
                    return;
                }

                JoinToRoom(false, roomName);
                MonitorStatus(true);
                manager.Start();
            }
            RefreshRoomlist();
            
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            WelcomeForm wf = new WelcomeForm();
            bool createResult = false;
            while (!createResult)
            {
                wf.ShowDialog();
                if (wf.DialogResult != DialogResult.OK)
                {
                    this.Close();
                    Application.Exit();
                    break;
                }
                else
                {
                    createResult = CreateUser(wf.UserName);
                }
            }
            lblUserName.Text = wf.UserName;
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            if (currentStatus == GameStatus.NoRoom)
            {
                MessageBox.Show("First join to room");
                return;
            }
            bool result;
            if (txtChatMsg.Text != "")
                result = manager.CheckAnswer(txtChatMsg.Text);
            txtChatMsg.Text = String.Empty;
        }

        private void MonitorStatus(bool newStatus)
        {
            if (manager != null)
            {
                manager.EnableGameStatusMonitor = newStatus;
            }
        }

        private void btnJoin_Click(object sender, EventArgs e)
        {
            JoinToRoom(true, null);
        }

        
        //Join or Leave        
        private void JoinToRoom(bool checkSelect, string CreatedRoom)
        { 
            if (Joined)
            {
                manager.LeaveRoom();
                txtRichChat.Text = "";
                btnJoin.Text = "Join";
                Joined = false;
                lblRoom.Text = "";
                listViewUsers.Items.Clear();
                return;
            }
            string room = "";
            if (checkSelect)
            {
                if (listBoxRooms.SelectedItem == null)
                    return;
                room = listBoxRooms.SelectedItem as string;
            }
            else
            {
                room = CreatedRoom;
            }

            var res = manager.Join(room);

            if (res == JoinResult.OK || res == JoinResult.AlreadyExists)
            {
                if (Joined == false)
                {
                    Joined = true;
                    btnJoin.Text = "Leave";
                    lblRoom.Text = room;
                    manager.CheckChat(true);
                    this.roomName = room;
                }
            }
            else if (res == JoinResult.ToManyUser)
                MessageBox.Show("ToManyUsers", "Look up!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            else if (res == JoinResult.Fail)
                MessageBox.Show("This room no longer exists", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            MonitorStatus(true);
        }

        private void btnStartGame_Click(object sender, EventArgs e)
        {
            if (currentStatus == GameStatus.During)
                return;
            if (currentStatus == GameStatus.NoRoom)
            {
                MessageBox.Show("First join to room");
                return;
            }
            var res = manager.iReady();
            switch (res)
            {
                case StartedGameStatus.NotEnoughPlayers:
                    MessageBox.Show("Not Enough players");
                    break;
                case StartedGameStatus.WaitingUntilAllPushTheStart:
                    btnStartGame.Text = "Waiting..";
                    break;
                case StartedGameStatus.Start:
                    break;
            }
            manager.Start();
        }

        private void listBoxUsersInRoom_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void btnRefreshUsers_Click(object sender, EventArgs e)
        {
            var result = manager.GetUserFromMyRoom();
            PopulateUserList(result);
        }

        private void PopulateUserList(List<User> Users)
        {
            InvokeOperation(() =>
            {
                List<User> localCopy = new List<User>(Users);
                listViewUsers.Items.Clear();                
                localCopy.ForEach(u =>
                {
                    if (u.Name == user.Name)
                        lblScore.Text = u.Points.ToString();
                    ListViewItem vi = new ListViewItem();
                    vi.Text = u.Name;
                    ListViewItem.ListViewSubItem vis = new ListViewItem.ListViewSubItem();
                    vis.Text = u.Points.ToString();
                    vi.SubItems.Add(vis);
                    listViewUsers.Items.Add(vi);
                });
            });
        }

        private void InvokeOperation(Action a)
        {
            try
            {
                this.Invoke(new Action(delegate()
                {
                    a();
                }));
            }
            catch (ObjectDisposedException) 
            {
                //exit 
            }

        }

        private void RoomTabControl_Selected(object sender, TabControlEventArgs e)
        {
            RefreshRoomlist();
        }

        private void RefreshRoomlist()
        {
            if (manager != null)
                manager.GetRooms();
        }

        private void txtChatMsg_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Enter)
                btnSend.PerformClick();
        }

        private void txtCreateRoom_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Enter)
                btnCreateRoom.PerformClick();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (Joined)
                manager.LeaveRoom();
            client.Close();
        }

        private void MainForm_Shown(object sender, EventArgs e)
        {
            if (!this.createdCompleted)
            {

            }
        }

       
    }
}
